﻿using EntityFramework.Data.Core;
using Framework.Common;
using Framework.Common.Exceptions;
using Framework.Common.Paged;
using IRepositories.Core;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Framework.Core;
using YouTravel.DomainModels;
using YouTravel.Framework.Enums;
using YouTravel.QueryModels;
using YouTravel.ViewModels;

namespace YouTravel.DomainService
{
    public class GatheringService : IGatheringService
    {
        readonly IEFRepository<Gathering> _gatheringRepository;
        public GatheringService(IUnitOfWork db, IEFRepository<Gathering> gatheringRepository)
        {
            this._gatheringRepository = gatheringRepository;
            this._gatheringRepository.SetDbContext(db);
        }
        /// <summary>
        /// 申请提交收款
        /// </summary>
        /// <param name="gathering"></param>
        /// <param name="operateUserId"></param>
        public void SubmitGathering(GatheringViewModel gathering, int operateUserId)
        {
            var loginUser = RedisHelp.GetLoginUserCacheNotNull(operateUserId);
            switch (loginUser.Type)
            {
                case UserType.Company:
                    throw new DataOperationPermissions("无此操作权限,总公司账号不能操作收款信息");
                case UserType.Branch:
                    throw new DataOperationPermissions("无此操作权限,分社账号不能申请提交收款");
                case 0:
                    throw new DataOperationPermissions("无此操作权限,超级管理员不能申请提交收款");
            }
            #region 数据验证
            if (!gathering.Bank.ValidateLen(30))
                throw new DataValidationException("付款银行名称长度必须在1-30个字符之间");
            if (!gathering.Drawee.ValidateLen(20))
                throw new DataValidationException("付款人姓名长度必须在1-20个字符之间");
            if (!gathering.GatheringBank.ValidateLen(20))
                throw new DataValidationException("付款银行帐号长度必须在1-20个字符之间");
            if (gathering.Money <= 0)
                throw new DataValidationException("付款金额必须大于0");
            if (!gathering.SerialNumber.ValidateLen(100))
                throw new DataValidationException("银行流水号长度必须在1-100个字符之间");
            #endregion

            var model = new Gathering();
            model.SpecialId = loginUser.SpecialId.Value;
            model.SpecialName = loginUser.Special.Name;
            model.SubmiterId = loginUser.ID;
            model.SubmiterName = loginUser.Name;
            model.SubmitTime = DateTime.Now;
            model.Bank = gathering.Bank;
            model.SerialNumber = gathering.SerialNumber;
            model.Money = gathering.Money;
            model.GatheringBank = gathering.GatheringBank;
            model.Drawee = gathering.Drawee;

            model.Status = GatheringStatus.WaitVerify;
            _gatheringRepository.Insert(model);
        }
        /// <summary>
        /// 审核提交收款信息
        /// </summary>
        /// <param name="gathering"></param>
        /// <param name="operateUserId"></param>
        public void AuditGathering(GatheringViewModel gathering, int operateUserId)
        {
            var loginUser = RedisHelp.GetLoginUserCacheNotNull(operateUserId);
            switch (loginUser.Type)
            {
                case UserType.Company:
                    throw new DataOperationPermissions("无此操作权限,总公司账号不能操作收款信息");
                case UserType.SpecialLine:
                    throw new DataOperationPermissions("无此操作权限,专线账号不能审核提交收款");
            }

            if (!string.IsNullOrEmpty(gathering.Remark) && gathering.Remark.Length > 200)
                throw new DataValidationException("收款备注不能超过200个汉字");
            if (gathering.Status == GatheringStatus.Discard && string.IsNullOrEmpty(gathering.Remark))
                throw new DataValidationException("当收款审核废弃时,收款备注不能为空");
            if (gathering.Status == GatheringStatus.WaitVerify)
                throw new DataValidationException("参数传入错误,当前接口收款状态参数不能为待收款");
            //得到查询
            var query = _gatheringRepository.GetModelTracking()
                .Include(p => p.Special.SpecialCapital)
                .Include(p => p.Special.Branch)
                .Where(p => p.ID == gathering.ID && p.Status == GatheringStatus.WaitVerify
                && p.Special.Status == SpecialStatus.Normal
                && p.Special.Branch.Status);

            var model = query.SingleOrDefault();
            if (model == null)
            {
                throw new BusinessException("此收款信息不存在");
            }
            if (loginUser.BranchId != model.Special.BranchId)
            {
                throw new DataOperationPermissions("无此操作权限,分社账号只能操作自身下属专线收款信息");
            }

            model.Remark = gathering.Remark;
            model.Status = gathering.Status;
            model.PayeeId = loginUser.ID;
            model.PayeeName = loginUser.Name;
            model.CollectionTime = DateTime.Now;

            #region 资金变动

            if (model.Status == GatheringStatus.HasReceiving)
            {
                model.Special.SpecialCapital.Balance += model.Money;
                model.Special.SpecialCapital.Gathering += model.Money;
                model.Special.SpecialCapital.Profit +=
                    DataProces.MoneyDataProce(model.Money * (model.Special.Branch.GrossMargin / 100));
            }

            #endregion

            _gatheringRepository.Update(model);
        }

        /// <summary>
        /// 得到收款详细
        /// </summary>
        /// <param name="gatheringId"></param>
        /// <param name="operateUserId"></param>
        /// <returns></returns>
        public GatheringViewModel GetModel(int gatheringId, int operateUserId)
        {

            var loginUser = RedisHelp.GetLoginUserCacheNotNull(operateUserId);

            //得到查询
            var query = _gatheringRepository.GetModel()
                .Include(p => p.Special)
                .Where(p => p.ID == gatheringId);

            var model = query.SingleOrDefault();
            if (model == null)
            {
                throw new BusinessException("此收款信息不存在");
            }
            switch (loginUser.Type)
            {
                case UserType.Company:
                    throw new DataOperationPermissions("无此访问权限,总公司账号不能查看收款信息");
                case UserType.Branch:
                    if (loginUser.BranchId != model.Special.BranchId)
                    {
                        throw new DataOperationPermissions("无此访问权限,分社账号只能查看他下属收款信息");
                    }
                    break;
                case UserType.SpecialLine:
                    if (loginUser.ID == model.SpecialId)
                    {
                        throw new DataOperationPermissions("无此访问权限,专线账号只能查看自身所在专线的收款信息");
                    }
                    break;
            }

            return query.SingleOrDefault().MapNew<Gathering, GatheringViewModel>();
        }
        /// <summary>
        /// 得到发票列表
        /// </summary>
        /// <param name="queryCond"></param>
        /// <returns></returns>
        public CustomPagedList<GatheringViewModel> GetList(PagedParam<GatheringQuery> queryCond)
        {
            //得到分页数据
            var result = _gatheringRepository.GetModel().GetPagedList(queryCond.PageDto.PageNo, queryCond.PageDto.PageSize,
                BuildQueryCondition(queryCond.QueryDto), queryCond.SortField)
                .ToCustomPagedList(u =>
                {
                    var s = u.MapNew<Gathering, GatheringViewModel>();
                    return s;
                });
            return result;
        }

        #region private
        /// <summary>
        /// 绑定查询条件
        /// 注:
        /// 分社      :    查询时条件不做限制 可查询所有状态信息
        /// 专线      :    当专线被冻结或销户后 是不能登录不能查询所有，所以下面就在做验证
        /// </summary>
        /// <param name="gatheringQuery"></param>
        /// <returns></returns>
        private Func<IQueryable<Gathering>, IQueryable<Gathering>> BuildQueryCondition(GatheringQuery gatheringQuery)
        {
            return query =>
            {
                if (gatheringQuery != null)
                {
                    #region 权限范围

                    var loginUser = RedisHelp.GetLoginUserCacheNotNull(gatheringQuery.LoginUserId);
                    switch (loginUser.Type)
                    {
                        case UserType.Company:
                            throw new DataOperationPermissions("无此访问权限,总公司账号不能查看发票");
                        case UserType.Branch://分站查询所有
                            query = query.Where(p => p.Special.BranchId == loginUser.BranchId);
                            break;
                        case UserType.SpecialLine://专线正常 分站正常
                            query = query.Where(p => p.Special.ID == loginUser.SpecialId
                                && p.Special.Status == SpecialStatus.Normal
                                && p.Special.Branch.Status);
                            break;
                    }
                    if (loginUser.Type != UserType.Branch && !string.IsNullOrEmpty(gatheringQuery.Name))
                        throw new DataOperationPermissions("无此访问权限,只有分社才能传入专线查询");
                    #endregion
                    //联查对象
                    query = query.Include(p => p.Special);

                    #region 查询条件


                    if (!string.IsNullOrEmpty(gatheringQuery.Name))
                    {
                        query = query.Where(p => p.Special.Name.Contains(gatheringQuery.Name) || p.Special.ChargeName.Contains(gatheringQuery.Name));
                    }
                    if (gatheringQuery.Status.HasValue)
                    {
                        query = query.Where(p => p.Status == gatheringQuery.Status.Value);
                    }
                    if (gatheringQuery.SubmitStartDate.HasValue)
                    {
                        var start = gatheringQuery.SubmitStartDate.Value.Date;
                        query = query.Where(p => p.SubmitTime >= start);
                    }
                    if (gatheringQuery.SubmitEndDate.HasValue)
                    {
                        var end = gatheringQuery.SubmitEndDate.Value.AddDays(1).Date;
                        query = query.Where(p => p.SubmitTime < end);
                    }
                    #endregion

                }
                return query;
            };
        }


        #endregion

    }
}
